ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
freemaster_serial.c
Go to the documentation of this file.
00001 /******************************************************************************
00002 *
00003 * Freescale Semiconductor Inc.
00004 * (c) Copyright 2004-2011 Freescale Semiconductor
00005 * ALL RIGHTS RESERVED.
00006 *
00007 ****************************************************************************/
00019 #include "freemaster.h"
00020 #include "freemaster_private.h"
00021 #include "freemaster_protocol.h"
00022 
00023 #if FMSTR_USE_SERIAL
00024 
00025 /***********************************
00026 *  local variables 
00027 ***********************************/
00028 
00029 /* FreeMASTER communication buffer (in/out) plus the STS and LEN bytes */
00030 static FMSTR_BCHR pcm_pCommBuffer[FMSTR_COMM_BUFFER_SIZE+3];    
00031 
00032 /* FreeMASTER runtime flags */
00033 /*lint -e{960} using union */
00034 typedef volatile union 
00035 {
00036     FMSTR_FLAGS all;
00037     
00038     struct
00039     {
00040         unsigned bTxActive : 1;         /* response is being transmitted */
00041 #if FMSTR_USE_SCI
00042         unsigned bTxWaitTC : 1;         /* response sent, wait for transmission complete */
00043 #endif
00044         unsigned bTxLastCharSOB   : 1;  /* last transmitted char was equal to SOB  */
00045         unsigned bRxLastCharSOB   : 1;  /* last received character was SOB */
00046         unsigned bRxMsgLengthNext : 1;  /* expect the length byte next time */
00047 #if FMSTR_USE_JTAG
00048         unsigned bJtagRIEPending  : 1;  /* JTAG RIE bit failed to be set, try again later */
00049 #endif
00050 #if FMSTR_USE_USB_CDC || FMSTR_USE_MQX_IO || FMSTR_USE_JTAG
00051         unsigned bTxFirstSobSend  : 1;  /* to send SOB char at the begin of the packet */
00052 #endif
00053 #if FMSTR_USE_MQX_IO
00054         unsigned bMqxReadyToSend  : 1;  /* to send next character in transmit routine */
00055 #endif
00056 #if FMSTR_USE_USB_CDC
00057         unsigned bUsbCdcStartApp   : 1; /* FreeMASTER USB CDC Application start Init Flag */
00058         unsigned bUsbCdcStartTrans : 1; /* FreeMASTER USB CDC Application Carrier Activate Flag */
00059         unsigned bUsbReadyToDecode : 1; /* FreeMASTER packet is received, ready to decode in Poll function in Short Interrupt mode */
00060 #endif
00061     } flg;
00062     
00063 } FMSTR_SERIAL_FLAGS;
00064 
00065 static FMSTR_SERIAL_FLAGS pcm_wFlags;
00066 
00067 /* receive and transmit buffers and counters */
00068 static FMSTR_SIZE8 pcm_nTxTodo;     /* transmission to-do counter (0 when tx is idle) */
00069 static FMSTR_SIZE8 pcm_nRxTodo;     /* reception to-do counter (0 when rx is idle) */
00070 static FMSTR_BPTR  pcm_pTxBuff;     /* pointer to next byte to transmit */
00071 static FMSTR_BPTR  pcm_pRxBuff;     /* pointer to next free place in RX buffer */
00072 static FMSTR_BCHR  pcm_nRxCheckSum; /* checksum of data being received */
00073 
00074 /***********************************
00075 *  local function prototypes
00076 ***********************************/
00077 
00078 static void FMSTR_Listen(void);
00079 static void FMSTR_SendError(FMSTR_BCHR nErrCode);
00080 
00081 #else /* FMSTR_USE_SERIAL */
00082 
00083 /*lint -efile(766, freemaster_protocol.h) include file is not used in this case */
00084 
00085 #endif /* FMSTR_USE_SERIAL */
00086 
00087 #if FMSTR_USE_SCI || FMSTR_USE_JTAG
00088 /***********************************
00089 *  local variables 
00090 ***********************************/
00091 
00092 /* SHORT_INTR receive queue (circular buffer) */
00093 #if FMSTR_SHORT_INTR
00094 static FMSTR_BCHR  pcm_pRQueueBuffer[FMSTR_COMM_RQUEUE_SIZE];
00095 static FMSTR_BPTR  pcm_pRQueueRP;   /* SHORT_INTR queue read-pointer */
00096 static FMSTR_BPTR  pcm_pRQueueWP;   /* SHORT_INTR queue write-pointer */
00097 #endif
00098 
00099 /***********************************
00100 *  local function prototypes
00101 ***********************************/
00102 
00103 #if FMSTR_SHORT_INTR
00104 static void FMSTR_RxQueue(FMSTR_BCHR nRxChar);
00105 static void FMSTR_RxDequeue(void);
00106 #endif
00107 
00108 /*lint -esym(752,FMSTR_RxQueue) this may be unreferenced in some cases */
00109 /*lint -esym(752,FMSTR_RxDequeue) this may be unreferenced in some cases */
00110 
00111 /*******************************************************************************
00112 *
00113 * @brief    Routine to quick-receive a character (put to a queue only)
00114 *
00115 * This function puts received character into a queue and exits as soon as possible.
00116 *
00117 *******************************************************************************/
00118 
00119 #if FMSTR_SHORT_INTR
00120 
00121 static void FMSTR_RxQueue(FMSTR_BCHR nRxChar)
00122 {
00123     /* future value of write pointer */
00124     FMSTR_BPTR wpnext = pcm_pRQueueWP + 1;
00125     
00126     /*lint -e{946} pointer arithmetic is okay here (same array) */
00127     if(wpnext >= (pcm_pRQueueBuffer + FMSTR_COMM_RQUEUE_SIZE))
00128     {
00129         wpnext = pcm_pRQueueBuffer;
00130     }
00131     
00132     /* any space in queue? */
00133     if(wpnext != pcm_pRQueueRP)
00134     {
00135         *pcm_pRQueueWP = (FMSTR_U8) nRxChar;
00136         pcm_pRQueueWP = wpnext;
00137     }
00138 }
00139 
00140 #endif /* FMSTR_SHORT_INTR  */
00141 
00142 /*******************************************************************************
00143 *
00144 * @brief    Late processing of queued characters
00145 *
00146 * This function takes the queued characters and calls FMSTR_Rx() for each of them,
00147 * just like as the characters would be received from SCI one by one.
00148 *
00149 *******************************************************************************/
00150 
00151 #if FMSTR_SHORT_INTR
00152 
00153 static void FMSTR_RxDequeue(void)
00154 { 
00155     FMSTR_BCHR nChar = 0U;
00156     
00157     /* get all queued characters */
00158     while(pcm_pRQueueRP != pcm_pRQueueWP)
00159     {
00160         nChar = *pcm_pRQueueRP++;
00161 
00162         /*lint -e{946} pointer arithmetic is okay here (same array) */
00163         if(pcm_pRQueueRP >= (pcm_pRQueueBuffer + FMSTR_COMM_RQUEUE_SIZE))
00164         {
00165             pcm_pRQueueRP = pcm_pRQueueBuffer;
00166         }
00167         
00168         /* emulate the SCI receive event */
00169         if(!pcm_wFlags.flg.bTxActive)
00170         {
00171             (void)FMSTR_Rx(nChar);
00172         }
00173     }
00174 }
00175 
00176 #endif /* FMSTR_SHORT_INTR */
00177 
00178 #endif /* FMSTR_USE_SCI || FMSTR_USE_JTAG */
00179 
00180 #if FMSTR_USE_SCI
00181 
00182 /**************************************************************************/
00192 void FMSTR_ProcessSCI(void)
00193 {
00194     /* read & clear status     */
00195     FMSTR_SCISR wSciSR = FMSTR_SCI_RDCLRSR();
00196 
00197     /* transmitter active and empty? */
00198     if (pcm_wFlags.flg.bTxActive)
00199     {
00200         /* able to accept another character? */
00201         if(wSciSR & FMSTR_SCISR_TDRE)
00202         {
00203             FMSTR_U8 ch;
00204             //(void)FMSTR_Tx(&ch);
00205             /* just put the byte into the SCI transmit buffer */
00206             if(!FMSTR_Tx(&ch))
00207                 FMSTR_SCI_PUTCHAR((FMSTR_U8) ch);
00208         }
00209         
00210 #if FMSTR_SCI_HAS_TXQUEUE
00211         /* waiting for transmission complete flag? */
00212         if(pcm_wFlags.flg.bTxWaitTC && (wSciSR & FMSTR_SCISR_TC))
00213         {
00214             /* after TC, we can switch to listen mode safely */
00215             FMSTR_Listen();
00216         }
00217 #endif
00218 
00219 
00220 #if !FMSTR_SCI_TWOWIRE_ONLY
00221         /* read-out and ignore any received character (loopback) */
00222         if(wSciSR & FMSTR_SCISR_RDRF)
00223         {
00224             /*lint -esym(550, nRxChar) */
00225             volatile FMSTR_U16 nRxChar;
00226             nRxChar = FMSTR_SCI_GETCHAR(); 
00227         }
00228 #endif
00229     }
00230     /* transmitter not active, able to receive */
00231     else
00232     {
00233         /* data byte received? */
00234         if (wSciSR & FMSTR_SCISR_RDRF)
00235         {
00236             FMSTR_BCHR nRxChar = 0U;
00237             nRxChar = (FMSTR_BCHR) FMSTR_SCI_GETCHAR();
00238 
00239 #if FMSTR_SHORT_INTR
00240             FMSTR_RxQueue(nRxChar);
00241 #else
00242             (void)FMSTR_Rx(nRxChar);  
00243 #endif          
00244         }
00245     }
00246 }
00247 
00248 #endif /* FMSTR_USE_SCI */
00249 
00250 
00251 #if FMSTR_USE_JTAG
00252 
00253 /***********************************
00254 *  local function prototypes
00255 ***********************************/
00256 
00257 static void FMSTR_FlushJtagTx(void);
00258 
00259 /**************************************************************************/
00268 static void FMSTR_FlushJtagTx(void)
00269 {
00270     FMSTR_U8 i;
00271     FMSTR_U32 wJtagTxData;
00272     register FMSTR_U16 wJtagSR = FMSTR_JTAG_GETSR();
00273     /* complete word to send */
00274     for (i=0; i<4; i++)
00275     {
00276         FMSTR_U8 ch;
00277         if (FMSTR_Tx(&ch))
00278             ch = 0xff;
00279         wJtagTxData = (wJtagTxData << 8) | ch;
00280     }
00281 
00282     /* send the word just completed */
00283     FMSTR_JTAG_PUTDWORD(wJtagTxData);
00284 }
00285 
00286 /**************************************************************************/
00296 void FMSTR_ProcessJTAG(void)
00297 {
00298     /* read & clear status     */
00299     register FMSTR_U16 wJtagSR = FMSTR_JTAG_GETSR();
00300 
00301     /* transmitter active? */
00302     if (pcm_wFlags.flg.bTxActive)
00303     {
00304         /* able to transmit a new character? (TX must be empty = read-out by PC) */
00305         if(!(wJtagSR & FMSTR_JTAG_OTXRXSR_TDF))
00306         {
00307         
00308 #if FMSTR_USE_JTAG_TXFIX
00309             /* if TDF bit is useless due to silicon bug, use the RX flag */
00310             /* instead (PC sends us a dummy word to kick the RX flag on) */
00311             if(wJtagSR & FMSTR_JTAG_OTXRXSR_RDF)
00312 #endif
00313             {
00314                 FMSTR_FlushJtagTx();
00315             }               
00316         }
00317 
00318         /* ignore (read-out) the JTAG-received word */
00319         if(wJtagSR & FMSTR_JTAG_OTXRXSR_RDF)
00320         {
00321             /*lint -esym(550, nRxWord) */
00322             volatile FMSTR_U16 nRxWord;
00323             nRxWord = FMSTR_JTAG_GETWORD();
00324         }
00325     }
00326     /* transmitter not active */
00327     else
00328     {
00329         /* JTAG 32bit word (four bytes) received? */
00330         if(wJtagSR & FMSTR_JTAG_OTXRXSR_RDF)
00331         {
00332             register FMSTR_U32 nRxDWord;
00333             FMSTR_INDEX i;
00334             
00335             nRxDWord = FMSTR_JTAG_GETDWORD();
00336             
00337             /* process all bytes, MSB first */
00338             for(i=0; i<4; i++)
00339             {
00340 #if FMSTR_SHORT_INTR
00341                 FMSTR_RxQueue((FMSTR_BCHR)((nRxDWord >> 24U) & 0xffU));
00342                 
00343 #else
00344                 (void)FMSTR_Rx((FMSTR_BCHR)((nRxDWord >> 24U) & 0xffU));
00345             
00346                 /* ignore the rest if previous bytes triggered a transmission */
00347                 /* (i.e. the packet was complete and only filled-up to 32bit word) */
00348                 if(pcm_wFlags.flg.bTxActive)
00349                 {
00350                     break;
00351                 }
00352 #endif          
00353                 /* next byte of 32bit word */
00354                 nRxDWord = nRxDWord << 8;
00355             }
00356         }
00357     }
00358 }
00359 
00360 #endif /* FMSTR_USE_JTAG */
00361 
00362 /******************************************************************************
00363 ****************************************************************************/
00369 #if FMSTR_USE_MQX_IO
00370 
00371 #include <mqx.h>
00372 #include <bsp.h>
00373 
00374 /***********************************
00375 *  local variables 
00376 ***********************************/
00377 
00378 static FILE_PTR devfd = NULL;       /* pointer to open FreeMASTER communication interface */
00379 
00380 /***********************************
00381 *  local function prototypes
00382 ***********************************/
00383 
00384 static FMSTR_BOOL FMSTR_InitMQX(void);
00385 static void FMSTR_ProcessMQXIO(void);
00386 
00387 /**************************************************************************/
00393 static FMSTR_BOOL FMSTR_InitMQX(void)
00394 {   
00395     /* Open communication port */
00396     devfd = fopen (FMSTR_MQX_IO_CHANNEL, (pointer) FMSTR_MQX_IO_PARAMETER);
00397 
00398     return (devfd != NULL);
00399 }
00400 
00401 /*******************************************************************************
00402 *
00403 * @brief    Handle MQX IO serial communication (both TX and RX)
00404 *
00405 * This function calls MQX IO fread() function to get character and process it by 
00406 * 
00407 * FMSTR_Rx function when FreeMASTER packet is receiving. This function also transmit
00408 *
00409 * FreeMASTER response. Character to be send is provided by call of FMSTR_Tx function 
00410 * 
00411 * and passed down to fwrite() function.
00412 *
00413 *******************************************************************************/
00414 
00415 static void FMSTR_ProcessMQXIO(void)
00416 { 
00417     if (devfd != NULL)
00418     {
00419          static FMSTR_U8 TxChar = 0;
00420         /* transmitter not active, able to receive */
00421         if ((!pcm_wFlags.flg.bTxActive) && (!pcm_wFlags.flg.bMqxReadyToSend))
00422         {
00423             FMSTR_U8 nRxChar;
00424             /* read all available bytes from communication interface */
00425             while (fread(&nRxChar, 1, 1, devfd)) { 
00426                 if(FMSTR_Rx(nRxChar))
00427                     break;
00428             }
00429         }
00430 
00431         /* transmitter active and empty? */
00432         if (pcm_wFlags.flg.bTxActive || pcm_wFlags.flg.bMqxReadyToSend)
00433         {
00434             while (1)
00435             {
00436                 /* write character when is valid */
00437                 if (pcm_wFlags.flg.bMqxReadyToSend)
00438                 {
00439                     if (fwrite(&TxChar, 1, 1, devfd))
00440                         /* character was successfully send, ready to get next character */
00441                         pcm_wFlags.flg.bMqxReadyToSend = 0;
00442                     else
00443                         /* character write failed, needs to be send next call */
00444                         break;
00445 
00446                 }
00447                 /* is ready to get next character? */
00448                 if (FMSTR_Tx((FMSTR_U8*)&TxChar))
00449                     /* FreeMASTER packet is sent, exit loop */
00450                     break;
00451                 /* read next character, set its validity to be send */
00452                 pcm_wFlags.flg.bMqxReadyToSend = 1;
00453             }
00454         }       
00455     }
00456 }
00457 
00458 #else /* FMSTR_USE_MQX_IO */
00459 
00460 /*lint -efile(766, freemaster_protocol.h) include file is not used in this case */
00461 
00462 #endif /* FMSTR_USE_MQX_IO */
00463 
00464 /******************************************************************************
00465 ****************************************************************************/
00471 #if FMSTR_USE_USB_CDC
00472 #include "usb_cdc.h"        /* USB CDC Class Header File */
00473 
00474 /***********************************
00475 *  Global variables
00476 ***********************************/
00477 FMSTR_U8 send_buf[DIC_BULK_IN_ENDP_PACKET_SIZE]; //buffer for store packet to send
00478 
00479 /***********************************
00480 *  local function prototypes
00481 ***********************************/
00482 
00483 static FMSTR_BOOL FMSTR_InitUSB(void);
00484 static void FMSTR_ProcessUSB(void);
00485 static void FMSTR_SendUsbPacket(void);
00486 
00487 static void FMSTR_USB_CDC_Callback(FMSTR_U8 controller_ID,
00488                         FMSTR_U8 event_type, void* val);
00489 static void FMSTR_USB_CDC_Notify_Callback(FMSTR_U8 controller_ID,
00490                         FMSTR_U8 event_type, void* val);
00491 
00492 /**************************************************************************/
00498 static FMSTR_BOOL FMSTR_InitUSB(void)
00499 {   
00500     FMSTR_U8   error;
00501 
00502     /* Initialize the USB interface */
00503     error = USB_Class_CDC_Init(FMSTR_USB_CDC_ID,FMSTR_USB_CDC_Callback,
00504                                 NULL,FMSTR_USB_CDC_Notify_Callback);
00505     if(error != USB_OK)
00506     {
00507         /* Error initializing USB-CDC Class */
00508         return FMSTR_FALSE;
00509     }
00510 
00511     return FMSTR_TRUE;
00512 }
00513 
00514 /**************************************************************************/
00522 static void FMSTR_ProcessUSB(void)
00523 { 
00524     /* call the periodic task function */
00525     USB_Class_CDC_Periodic_Task();
00526 
00527 #if FMSTR_SHORT_INTR
00528     /*check whether enumeration is complete or not */
00529     if((pcm_wFlags.flg.bUsbCdcStartApp) && (pcm_wFlags.flg.bUsbCdcStartTrans))
00530     {
00531         /*transmitter not active, able to receive */
00532         if ((!pcm_wFlags.flg.bTxActive) && (pcm_wFlags.flg.bUsbReadyToDecode))
00533         {
00534             FMSTR_ProtocolDecoder(pcm_pCommBuffer);
00535             pcm_wFlags.flg.bUsbReadyToDecode = 0;
00536         }
00537     }
00538 #endif  
00539 }
00540 
00541 
00542 /**************************************************************************/
00552 static void FMSTR_SendUsbPacket(void)
00553 {
00554     /* transmitter active and empty? */
00555     if (pcm_wFlags.flg.bTxActive)
00556     {
00557         FMSTR_U8 index;
00558 
00559         /* fill in the transmitter buffer */
00560         for (index = 0; index < DIC_BULK_IN_ENDP_PACKET_SIZE; index++){
00561             FMSTR_U8 TxChar;
00562             if (FMSTR_Tx(&TxChar))
00563                 break;
00564             send_buf[index] = TxChar;
00565         }
00566         
00567        USB_Class_CDC_Interface_DIC_Send_Data(FMSTR_USB_CDC_ID, send_buf,index);
00568     }
00569 }
00570 
00571 /******************************************************************************
00572  *
00573  *    @name        FMSTR_USB_CDC_Callback
00574  *
00575  *    @brief       This function handles Class callback
00576  *
00577  *    @param       controller_ID    : Controller ID
00578  *    @param       event_type       : Value of the event
00579  *    @param       val              : gives the configuration value
00580  *
00581  *    @return      None
00582  *
00583  *****************************************************************************
00584  * This function is called from the class layer whenever reset occurs or enum
00585  * is complete. After the enum is complete this function sets a variable so
00586  * that the application can start.
00587  * This function also receives DATA Send and RECEIVED Events
00588  *****************************************************************************/
00589 
00590 static void FMSTR_USB_CDC_Callback (
00591     FMSTR_U8 controller_ID,   /* [IN] Controller ID */
00592     FMSTR_U8 event_type,      /* [IN] value of the event */
00593     void* val               /* [IN] gives the configuration value */
00594 )
00595 {
00596     UNUSED (controller_ID)
00597     UNUSED (val)
00598     if(event_type == USB_APP_BUS_RESET)
00599     {
00600         pcm_wFlags.flg.bUsbCdcStartApp = 0U;
00601     }
00602     else if(event_type == USB_APP_ENUM_COMPLETE)
00603     {
00604         pcm_wFlags.flg.bUsbCdcStartApp = 1U;
00605     }
00606     else if((event_type == USB_APP_DATA_RECEIVED) && (pcm_wFlags.flg.bUsbCdcStartTrans))
00607     {
00608         /* manage received data */
00609         if (pcm_wFlags.flg.bUsbCdcStartApp)
00610         {
00611             /* Copy Received Data buffer to Application Buffer */
00612             USB_PACKET_SIZE BytesToBeCopied;
00613             APP_DATA_STRUCT* dp_rcv = (APP_DATA_STRUCT*)val;
00614             BytesToBeCopied = dp_rcv->data_size;
00615 
00616             /* transmitter not active, able to receive */
00617             if (!pcm_wFlags.flg.bTxActive)
00618             {
00619                 FMSTR_U8 index;
00620                 for(index = 0 ; index<BytesToBeCopied ; index++){
00621                     if(FMSTR_Rx(dp_rcv->data_ptr[index])){
00622                         break;
00623                     }
00624                 }
00625                 /* continue receiving, when packet is not decoded */
00626                 if (index == BytesToBeCopied) /* receive next packet only when are not received all bytes of packet */
00627                     (void)USB_Class_CDC_Interface_DIC_Recv_Data(FMSTR_USB_CDC_ID, NULL, 0);
00628             }
00629         }
00630     }
00631     else if((event_type == USB_APP_SEND_COMPLETE) && (pcm_wFlags.flg.bUsbCdcStartTrans))
00632     {
00633         if ((pcm_wFlags.flg.bUsbCdcStartApp) && (pcm_wFlags.flg.bTxActive))
00634             /* Finalize USB packet to transmit and send packet */
00635             FMSTR_SendUsbPacket();
00636         else
00637             /* Previous Send is complete. Queue next receive */
00638             (void)USB_Class_CDC_Interface_DIC_Recv_Data(FMSTR_USB_CDC_ID, NULL, 0);
00639     }
00640 
00641     return;
00642 }
00643 
00644 /******************************************************************************
00645  *
00646  *    @name        FMSTR_USB_CDC_Notify_Callback
00647  *
00648  *    @brief       This function handles PSTN Sub Class callbacks
00649  *
00650  *    @param       controller_ID    : Controller ID
00651  *    @param       event_type       : PSTN Event Type
00652  *    @param       val              : gives the configuration value
00653  *
00654  *    @return      None
00655  *
00656  *****************************************************************************
00657  * This function handles USB_APP_CDC_CARRIER_ACTIVATED and
00658  * USB_APP_CDC_CARRIER_DEACTIVATED PSTN Events
00659  *****************************************************************************/
00660 
00661 static void FMSTR_USB_CDC_Notify_Callback (
00662     FMSTR_U8 controller_ID,   /* [IN] Controller ID */
00663     FMSTR_U8 event_type,      /* [IN] PSTN Event Type */
00664     void* val               /* [IN] gives the configuration value */
00665 )
00666 {
00667     UNUSED (controller_ID)
00668     UNUSED (val)
00669     if(pcm_wFlags.flg.bUsbCdcStartApp)
00670     {
00671         if(event_type == USB_APP_CDC_CARRIER_ACTIVATED)
00672         {
00673             pcm_wFlags.flg.bUsbCdcStartTrans = 1U;
00674         }
00675         else if(event_type == USB_APP_CDC_CARRIER_DEACTIVATED)
00676         {
00677             pcm_wFlags.flg.bUsbCdcStartTrans = 0U;
00678         }
00679     }
00680     return;
00681 }
00682 
00683 #else /* FMSTR_USE_USB_CDC */
00684 
00685 /*lint -efile(766, freemaster_protocol.h) include file is not used in this case */
00686 
00687 #endif /* FMSTR_USE_USB_CDC */
00688 
00689 
00690 #if FMSTR_USE_SERIAL
00691 
00692 /**************************************************************************/
00700 static void FMSTR_Listen(void)
00701 {
00702     pcm_nRxTodo = 0U;
00703 
00704     /* disable transmitter state machine */
00705     pcm_wFlags.flg.bTxActive = 0U;
00706 
00707 #if FMSTR_USE_SCI
00708     pcm_wFlags.flg.bTxWaitTC = 0U;
00709     /* disable transmitter, enable receiver (enables single-wire connection) */
00710 #if !FMSTR_SCI_TWOWIRE_ONLY
00711     FMSTR_SCI_TD();
00712     FMSTR_SCI_RE();
00713 #endif
00714 #endif /* FMSTR_USE_SCI */
00715 
00716     /* disable transmit, enable receive interrupts */
00717 #if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
00718 #if FMSTR_USE_SCI
00719     FMSTR_SCI_DTXI();   /* disable SCI transmit interrupt */
00720     FMSTR_SCI_ERXI();   /* enable SCI receive interrupt */
00721     
00722 #elif FMSTR_USE_JTAG
00723     FMSTR_JTAG_DTXI();  /* disable JTAG transmit interrupt  */
00724     FMSTR_JTAG_ERXI();  /* enable JTAG receive interrupt  */
00725 
00726     /* RIE bit is forced low by HW until EONCE is first accessed, we will try again in FMSTR_Poll */
00727     if(!FMSTR_JTAG_ERXI_CHECK())
00728         pcm_wFlags.flg.bJtagRIEPending = 1;
00729 
00730 #endif /* FMSTR_USE_SCI / FMSTR_USE_JTAG  */
00731 #endif /* FMSTR_SHORT_INTR || FMSTR_LONG_INTR */
00732 }
00733 
00734 /**************************************************************************/
00742 static void FMSTR_SendError(FMSTR_BCHR nErrCode)
00743 {
00744     /* fill & send single-byte response */
00745     *pcm_pCommBuffer = nErrCode;
00746     FMSTR_SendResponse(pcm_pCommBuffer, 1U);
00747 }
00748 
00749 /**************************************************************************/
00761 void FMSTR_SendResponse(FMSTR_BPTR pResponse, FMSTR_SIZE8 nLength)
00762 {
00763     FMSTR_U16 chSum = 0U;
00764     FMSTR_U8 i, c;
00765 
00766     /* remember the buffer to be sent */
00767     pcm_pTxBuff = pResponse;
00768     
00769     /* status byte and data are already there, compute checksum only     */
00770     for (i=0U; i<nLength; i++)
00771     {
00772         c = 0U;
00773         pResponse = FMSTR_ValueFromBuffer8(&c, pResponse);
00774         /* add character to checksum */
00775         chSum += c;
00776         /* prevent saturation to happen on DSP platforms */
00777         chSum &= 0xffU;
00778     }
00779     
00780     /* store checksum after the message */
00781     pResponse = FMSTR_ValueToBuffer8(pResponse, (FMSTR_U8) (((FMSTR_U16)~(chSum)) + 1U));
00782 
00783     /* send the message and the checksum and the SOB */
00784     pcm_nTxTodo = (FMSTR_SIZE8) (nLength + 1U); 
00785     
00786     /* now transmitting the response */
00787     pcm_wFlags.flg.bTxActive = 1U;
00788 
00789 #if FMSTR_USE_USB_CDC || FMSTR_USE_MQX_IO || FMSTR_USE_JTAG
00790     pcm_wFlags.flg.bTxFirstSobSend = 1U;
00791 #endif
00792 
00793 #if FMSTR_USE_SCI
00794     pcm_wFlags.flg.bTxWaitTC = 0U;
00795 #endif
00796 
00797     /* do not replicate the initial SOB  */
00798     pcm_wFlags.flg.bTxLastCharSOB = 0U;
00799     
00800 #if FMSTR_USE_SCI       
00801     {
00802         /*lint -esym(550, dummySR) */        
00803         volatile FMSTR_SCISR dummySR;
00804 
00805         /* disable receiver, enable transmitter (single-wire communication) */
00806 #if !FMSTR_SCI_TWOWIRE_ONLY
00807         FMSTR_SCI_RD();
00808         FMSTR_SCI_TE();
00809 #endif        
00810         /* kick on the SCI transmission (also clears TX Empty flag on some platforms) */
00811         dummySR = FMSTR_SCI_GETSR();
00812         FMSTR_SCI_PUTCHAR(FMSTR_SOB);
00813     }
00814     
00815 #elif FMSTR_USE_JTAG
00816     /* kick on the JTAG transmission */
00817     FMSTR_FlushJtagTx();
00818 #endif
00819 
00820     /* TX interrupt enable, RX interrupt disable */
00821 #if FMSTR_LONG_INTR || FMSTR_SHORT_INTR
00822 #if FMSTR_USE_SCI       
00823     FMSTR_SCI_DRXI();
00824     FMSTR_SCI_ETXI();
00825     
00826 #elif FMSTR_USE_JTAG
00827 #if FMSTR_USE_JTAG_TXFIX
00828     /* in TX-bugfix mode, keep the RX interrupt enabled as it */
00829     /* is used as "able-to-TX" notification from the PC */
00830     FMSTR_JTAG_ERXI();
00831 #else
00832     /* otherwise, JTAG is very same as the SCI */
00833     if(pcm_wFlags.flg.bTxActive) //enable TX interrupt only when is not one word response 
00834     {
00835         FMSTR_JTAG_DRXI();
00836         FMSTR_JTAG_ETXI();
00837     }
00838 #endif              
00839 
00840 #elif FMSTR_USE_USB_CDC
00841     if ((pcm_wFlags.flg.bUsbCdcStartApp) && (pcm_wFlags.flg.bTxActive) && (pcm_wFlags.flg.bUsbCdcStartTrans))
00842         /* Finalize USB packet to transmit and send packet */
00843         FMSTR_SendUsbPacket();
00844     else
00845         /* Previous Send is complete. Queue next receive */
00846         (void)USB_Class_CDC_Interface_DIC_Recv_Data(FMSTR_USB_CDC_ID, NULL, 0);
00847 #endif
00848 #endif /* FMSTR_LONG_INTR || FMSTR_SHORT_INTR */      
00849 }
00850 
00851 /**************************************************************************/
00861 FMSTR_BOOL FMSTR_Tx(FMSTR_U8* pTxChar)
00862 {
00863 #if FMSTR_USE_USB_CDC || FMSTR_USE_MQX_IO || FMSTR_USE_JTAG
00864     /* to send first SOB byte*/
00865     if (pcm_wFlags.flg.bTxFirstSobSend)
00866     {
00867         *pTxChar = FMSTR_SOB;
00868         pcm_wFlags.flg.bTxFirstSobSend = 0U;
00869         return FMSTR_FALSE;
00870     }
00871 #endif      
00872     if (pcm_nTxTodo)
00873     {
00874         /* fetch & send character ready to transmit */
00875         /*lint -e{534} ignoring return value */
00876         FMSTR_ValueFromBuffer8(pTxChar, pcm_pTxBuff);
00877         
00878         /* first, handle the replicated SOB characters */
00879         if (*pTxChar == FMSTR_SOB)
00880         {
00881             pcm_wFlags.flg.bTxLastCharSOB ^= 1U;
00882             if ((pcm_wFlags.flg.bTxLastCharSOB))
00883             {
00884                 /* yes, repeat the SOB next time */
00885                 return FMSTR_FALSE;
00886             }
00887         }
00888         /* no, advance tx buffer pointer */
00889         pcm_nTxTodo--;
00890         pcm_pTxBuff = FMSTR_SkipInBuffer(pcm_pTxBuff, 1U);
00891         return FMSTR_FALSE;
00892     }
00893     
00894     /* when SCI TX buffering is enabled, we must first wait until all 
00895        characters are physically transmitted (before disabling transmitter) */
00896 #if FMSTR_USE_SCI
00897   #if FMSTR_SCI_HAS_TXQUEUE
00898     pcm_wFlags.flg.bTxWaitTC = 1;
00899 
00900     /* wait for SCI TC interrupt */
00901     #if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
00902     FMSTR_SCI_ETCI();
00903     #endif
00904   #else
00905     /* start listening immediately */
00906     FMSTR_Listen();
00907   #endif  
00908 #else
00909     /* start listening immediately */
00910     FMSTR_Listen();
00911 #endif
00912 
00913     return FMSTR_TRUE;
00914 }
00915 
00916 
00917 /**************************************************************************/
00928 FMSTR_BOOL FMSTR_Rx(FMSTR_BCHR nRxChar)
00929 {
00930     FMSTR_SERIAL_FLAGS * pflg = &pcm_wFlags;
00931     /* first, handle the replicated SOB characters */
00932     if(nRxChar == FMSTR_SOB)
00933     {
00934         pflg->flg.bRxLastCharSOB ^= 1;
00935         if(pflg->flg.bRxLastCharSOB)
00936         {
00937             /* this is either the first byte of replicated SOB or a  */
00938             /* real Start-of-Block mark - we will decide next time in FMSTR_Rx */
00939             return FMSTR_FALSE;
00940         }
00941     }
00942     
00943     /* we have got a common character preceded by the SOB -  */
00944     /* this is the command code! */
00945     if(pflg->flg.bRxLastCharSOB)
00946     {
00947         /* reset receiving process */
00948         pcm_pRxBuff = pcm_pCommBuffer;
00949         *pcm_pRxBuff++ = nRxChar;
00950 
00951         /* start computing the checksum */
00952         pcm_nRxCheckSum = nRxChar;
00953         pcm_nRxTodo = 0U;
00954     
00955         /* if the standard command was received, the message length will come in next byte */
00956         pflg->flg.bRxMsgLengthNext = 1U;
00957 
00958         /* fast command? */
00959         if(!((~nRxChar) & FMSTR_FASTCMD))
00960         {
00961             /* fast command received, there will be no length information */
00962             pflg->flg.bRxMsgLengthNext = 0U;
00963             /* as it is encoded in the command byte directly */
00964             pcm_nRxTodo = (FMSTR_SIZE8) 
00965                 (((((FMSTR_SIZE8)nRxChar) & FMSTR_FASTCMD_DATALEN_MASK) >> FMSTR_FASTCMD_DATALEN_SHIFT) + 1U);
00966         }
00967 
00968         /* command code stored & processed */
00969         pflg->flg.bRxLastCharSOB = 0U;
00970         return FMSTR_FALSE;
00971     }
00972 
00973     /* we are waiting for the length byte */
00974     if(pflg->flg.bRxMsgLengthNext)
00975     {
00976         /* this byte, total data length and the checksum */
00977         pcm_nRxTodo = (FMSTR_SIZE8) (1U + ((FMSTR_SIZE8)nRxChar) + 1U);
00978         /* now read the data bytes */
00979         pflg->flg.bRxMsgLengthNext = 0U;
00980 
00981     }
00982 
00983     /* waiting for a data byte? */
00984     if(pcm_nRxTodo)
00985     {
00986         /* add this byte to checksum */
00987         pcm_nRxCheckSum += nRxChar;
00988 
00989         /* decrease number of expected bytes */
00990         pcm_nRxTodo--;
00991         /* was it the last byte of the message (checksum)? */
00992         if(!pcm_nRxTodo)
00993         {
00994             /* receive buffer overflow? */
00995             if(pcm_pRxBuff == NULL)
00996             {
00997                 FMSTR_SendError(FMSTR_STC_CMDTOOLONG);
00998             }
00999             /* checksum error? */
01000             else if((pcm_nRxCheckSum & 0xffU) != 0U)
01001             {
01002                 FMSTR_SendError(FMSTR_STC_CMDCSERR);
01003             }
01004             /* message is okay */
01005             else 
01006             {
01007 #if FMSTR_USE_USB_CDC && FMSTR_SHORT_INTR
01008                 /* Decode protocol and send response in Poll function */
01009                 pflg->flg.bUsbReadyToDecode = 1U;
01010 #else
01011                 /* do decode now! */
01012                 FMSTR_ProtocolDecoder(pcm_pCommBuffer);
01013 #endif
01014             }
01015 
01016             return FMSTR_TRUE;
01017         }
01018         /* not the last character yet */
01019         else 
01020         {   
01021             /* is there still a space in the buffer? */
01022             if(pcm_pRxBuff)
01023             {
01024                 /*lint -e{946} pointer arithmetic is okay here (same array) */
01025                 if(pcm_pRxBuff < (pcm_pCommBuffer + FMSTR_COMM_BUFFER_SIZE))
01026                 {
01027                     /* store byte  */
01028                     *pcm_pRxBuff++ = nRxChar;
01029                 }
01030                 /* buffer is full! */
01031                 else
01032                 {
01033                     /* NULL rx pointer means buffer overflow - but we still need */
01034                     /* to receive all message characters (for the single-wire mode) */
01035                     /* so keep "receiving" - but throw away all characters from now */
01036                     pcm_pRxBuff = NULL;
01037                 }
01038             }
01039         }
01040     }
01041     return FMSTR_FALSE; 
01042 }
01043 
01044 /**************************************************************************/
01050 FMSTR_BOOL FMSTR_InitSerial(void)
01051 {   
01052     /* initialize all state variables */
01053     pcm_wFlags.all = 0U;
01054     pcm_nTxTodo = 0U;
01055 
01056 /* Initialize SCI and JTAG interface */
01057 #if FMSTR_USE_SCI && FMSTR_SCI_TWOWIRE_ONLY
01058     /* to enable TX and RX together in FreeMASTER initialization */
01059     FMSTR_SCI_TE_RE();
01060 #endif
01061     
01062 #if FMSTR_SHORT_INTR & (FMSTR_USE_SCI || FMSTR_USE_JTAG)
01063     pcm_pRQueueRP = pcm_pRQueueBuffer;
01064     pcm_pRQueueWP = pcm_pRQueueBuffer;
01065 #endif
01066 
01067 #if FMSTR_USE_MQX_IO
01068     if (!FMSTR_InitMQX())
01069         return FMSTR_FALSE;
01070 #endif
01071 
01072 #if FMSTR_USE_USB_CDC
01073         if (!FMSTR_InitUSB())
01074                 return FMSTR_FALSE;
01075 #endif
01076 
01077     /* start listening for commands */
01078     FMSTR_Listen();
01079     return FMSTR_TRUE;
01080 }
01081 
01082 
01083 /*******************************************************************************
01084 *
01085 * @brief    API: Main "Polling" call from the application main loop
01086 *
01087 * This function either handles all the SCI communication (polling-only mode = 
01088 * FMSTR_POLL_DRIVEN) or decodes messages received on the background by SCI interrupt
01089 * (short-interrupt mode = FMSTR_SHORT_INTR). 
01090 *
01091 * In the JTAG interrupt-driven mode (both short and long), this function also checks
01092 * if setting the JTAG RIE bit failed recently. This may happen because of the 
01093 * RIE is held low by the EONCE hardware until the EONCE is first accessed from host.
01094 * FMSTR_Init (->FMSTR_Listen) is often called while the PC-side FreeMASTER is still 
01095 * turned off. So really, the JTAG is not enabled by this time and RIE bit is not set.
01096 * This problem is detected (see how bJtagRIEPending is set above in FSMTR_Listen)
01097 * and it is tried to be fixed periodically here in FMSTR_Poll.
01098 *
01099 *******************************************************************************/
01100 
01101 void FMSTR_Poll(void)
01102 { 
01103 #if !FMSTR_POLL_DRIVEN && FMSTR_USE_JTAG
01104     /* in the interrupt-driven JTAG mode, the JTAG RIE may have failed to be set recently */
01105     if(pcm_wFlags.flg.bJtagRIEPending)
01106     {
01107         FMSTR_JTAG_ERXI();  /* try to enable JTAG receive interrupt now */
01108 
01109         /* succeeded? */
01110         if(FMSTR_JTAG_ERXI_CHECK())
01111             pcm_wFlags.flg.bJtagRIEPending = 0; /* yes!, enough until it fails again (never?) */
01112     }
01113 #endif    
01114 
01115 #if FMSTR_USE_MQX_IO
01116     /* polled MQX IO mode */
01117     FMSTR_ProcessMQXIO(); 
01118 #endif
01119 
01120 #if FMSTR_POLL_DRIVEN
01121 
01122 #if FMSTR_USE_SCI
01123     /* polled SCI mode */
01124     FMSTR_ProcessSCI(); 
01125     
01126 #elif FMSTR_USE_JTAG
01127     /* polled JTAG mode */
01128     FMSTR_ProcessJTAG(); 
01129 #endif
01130     
01131 #elif FMSTR_SHORT_INTR 
01132 
01133 #if FMSTR_USE_USB_CDC
01134     /*  */
01135     FMSTR_ProcessUSB();
01136 #elif (FMSTR_USE_SCI || FMSTR_USE_JTAG)
01137 
01138     /* process queued SCI characters */
01139     FMSTR_RxDequeue(); 
01140 #endif  
01141   
01142 #endif
01143 }
01144 
01145 #endif